package cn.lili.controller.goods;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.cache.LockPrefix;
import cn.lili.common.aop.annotation.PreventDuplicateSubmissions;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.OperationalJudgment;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.security.enums.SceneEnums;
import cn.lili.common.utils.ResultUtil;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.distribution.entity.vos.HomeResult;
import cn.lili.modules.goods.entity.dos.Goods;
import cn.lili.modules.goods.entity.dos.GoodsDownRecord;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.dto.*;
import cn.lili.modules.goods.entity.enums.GoodsMarketEnum;
import cn.lili.modules.goods.entity.vos.GoodsSkuVO;
import cn.lili.modules.goods.entity.vos.GoodsVO;
import cn.lili.modules.goods.entity.vos.StockWarningVO;
import cn.lili.modules.goods.integration.GoodsIntegrationService;
import cn.lili.modules.goods.service.GoodsDownRecordService;
import cn.lili.modules.goods.service.GoodsService;
import cn.lili.modules.goods.service.GoodsSkuService;
import cn.lili.modules.operationcenter.entity.dto.OperationCenterSupplierDTO;
import cn.lili.modules.operationcenter.entity.vos.OperationCenterSupplierVo;
import cn.lili.modules.statistics.aop.PageViewPoint;
import cn.lili.modules.statistics.aop.enums.PageViewEnum;
import cn.lili.modules.store.client.StoreClient;
import cn.lili.modules.store.entity.vos.StoreVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 商品管理接口
 *
 * @author pikachu
 * @since 2020-02-23 15:18:56
 */
@Slf4j
@RestController
@Api(tags = "商品管理接口")
@RequiredArgsConstructor
@RequestMapping("/goods")
public class GoodsController {

    private final GoodsService goodsService;

    private final GoodsSkuService goodsSkuService;

    private final GoodsIntegrationService goodsIntegrationService;

    private final StoreClient storeClient;

    private final RedissonClient redisson;

    private final GoodsDownRecordService goodsDownRecordService;

    @ApiOperation(value = "分页获取")
    @GetMapping
    public ResultMessage<IPage<GoodsVO>> getByPage(GoodsSearchParams goodsSearchParams) {
        log.info("进来了");
        return ResultUtil.data(goodsService.queryByParams(goodsSearchParams));
    }


    @ApiOperation(value = "分页获取商品列表")
    @GetMapping(value = "/sku/list")
    public ResultMessage<Page<GoodsSku>> getSkuByPage(GoodsSearchParams goodsSearchParams) {
        return ResultUtil.data(goodsSkuService.getGoodsSkuByPage(goodsSearchParams));
    }

    @ApiOperation(value = "分页获取商品列表")
    @GetMapping(value = "/getGoodsByPage")
    public ResultMessage<Page<Goods>> getGoodsByPage(GoodsSearchParams goodsSearchParams) {
        return ResultUtil.data(goodsService.getGoodsByPage(goodsSearchParams));
    }

    @ApiOperation(value = "根据goodsId分页获取商品规格列表")
    @GetMapping(value = "/sku/{goodsId}/list")
    public ResultMessage<List<GoodsSkuVO>> getSkuByList(@PathVariable String goodsId) {
        String storeId = Objects.requireNonNull(UserContext.getCurrentUser()).getExtendId();
        return ResultUtil.data(goodsSkuService.getGoodsSkuVOList(goodsSkuService.list(new LambdaQueryWrapper<GoodsSku>().eq(GoodsSku::getGoodsId,
                goodsId).eq(GoodsSku::getStoreId, storeId))));
    }

    @ApiOperation(value = "根据goodsId分页获取商品规格列表")
    @GetMapping(value = "/sku/{goodsId}/{storeId}/list")
    public ResultMessage<List<GoodsSkuVO>> getSkuByList(@PathVariable String goodsId,@PathVariable String storeId) {
        assert CharSequenceUtil.isNotEmpty(storeId);
        return ResultUtil.data(goodsSkuService.getGoodsSkuVOList(goodsSkuService.list(new LambdaQueryWrapper<GoodsSku>().eq(GoodsSku::getGoodsId,
                goodsId).eq(GoodsSku::getStoreId, storeId))));
    }

    @ApiOperation(value = "分页获取库存告警商品列表")
    @GetMapping(value = "/list/stock")
    public ResultMessage<StockWarningVO> getWarningStockByPage(GoodsSearchParams goodsSearchParams) {
        //获取当前登录商家账号
        String storeId = Objects.requireNonNull(UserContext.getCurrentUser()).getExtendId();
        StoreVO store = OperationalJudgment.judgment(storeClient.getStore(storeId));
        Integer stockWarnNum = store.getStockWarning();
        goodsSearchParams.setStoreId(storeId);
        goodsSearchParams.setLeQuantity(stockWarnNum);
        goodsSearchParams.setMarketEnable(GoodsMarketEnum.UPPER.name());
        Page<GoodsSku> goodsSku = goodsSkuService.getGoodsSkuByPage(goodsSearchParams);
        StockWarningVO stockWarning = new StockWarningVO(stockWarnNum, goodsSku);
        return ResultUtil.data(stockWarning);
    }

    @PreventDuplicateSubmissions
    @ApiOperation(value = "管理商品状态", notes = "管理商品状态")
    @PutMapping(value = "/update/status")
    public ResultMessage<Object> underGoods(@RequestBody GoodsUpdateStatusDTO goodsUpdateStatusDTO) {
        AuthUser authUser = Objects.requireNonNull(UserContext.getCurrentUser());
        if (!SceneEnums.MANAGER.equals(authUser.getScene())) {
            goodsUpdateStatusDTO.setStoreId(authUser.getExtendId());
        }
        goodsIntegrationService.updateGoodsStatus(goodsUpdateStatusDTO);
        return ResultUtil.success();
    }

    @PreventDuplicateSubmissions
    @ApiOperation(value = "批量增加商品虚拟销量", notes = "批量增加商品虚拟销量")
    @PutMapping(value = "/update/sales/volume")
    public ResultMessage<Boolean> updateSalesVolume(@RequestBody GoodsUpdateStatusDTO goodsUpdateStatusDTO) {
        AuthUser authUser = Objects.requireNonNull(UserContext.getCurrentUser());
        if (!SceneEnums.MANAGER.equals(authUser.getScene())) {
            goodsUpdateStatusDTO.setStoreId(authUser.getExtendId());
        }
        return ResultUtil.data(goodsIntegrationService.updateSalesVolume(goodsUpdateStatusDTO));
    }

    @PreventDuplicateSubmissions
    @ApiOperation(value = "批量增加商品虚拟评价", notes = "批量增加商品虚拟评价")
    @PutMapping(value = "/update/evaluate/volume")
    public ResultMessage<Boolean> updateEvaluateVolume(@RequestBody GoodsUpdateStatusDTO goodsUpdateStatusDTO) {
        AuthUser authUser = Objects.requireNonNull(UserContext.getCurrentUser());
        if (!SceneEnums.MANAGER.equals(authUser.getScene())) {
            goodsUpdateStatusDTO.setStoreId(authUser.getExtendId());
        }
        return ResultUtil.data(goodsIntegrationService.updateEvaluateVolume(goodsUpdateStatusDTO));
    }


    @ApiOperation(value = "新增商品")
    @PostMapping
    public ResultMessage<GoodsOperationDTO> save(@Valid @RequestBody GoodsOperationDTO goodsOperationDTO) {
        if (Objects.requireNonNull(UserContext.getCurrentUser()).getScene().equals(SceneEnums.STORE)) {
            goodsIntegrationService.saveGoods(goodsOperationDTO);
            return ResultUtil.success();
        } else {
            return ResultUtil.error();
        }
    }

    @ApiOperation(value = "修改商品")
    @PutMapping(value = "/{goodsId}")
    public ResultMessage<GoodsOperationDTO> update(@PathVariable String goodsId, @Valid @RequestBody GoodsOperationDTO goodsOperationDTO) {
        if (Objects.requireNonNull(UserContext.getCurrentUser()).getScene().equals(SceneEnums.STORE)) {
            goodsOperationDTO.setGoodsId(goodsId);
            goodsIntegrationService.updateGoods(goodsOperationDTO);
            return ResultUtil.success();
        } else {
            return ResultUtil.error(500,"账号不适合修改此信息");
        }
    }

    @GetMapping("/sycn")
    public ResultMessage<Object> sycn() {
        return goodsService.sycn();
    }

    /**
     * 修改商品分类
     *
     * @param goodsOperationDTO goodsIds 商品ids, categoryPathIds 分类ids
     * @return
     */
    @ApiOperation(value = "修改商品")
    @PostMapping(value = "/update/ids")
    public ResultMessage<GoodsOperationDTO> update(@RequestBody GoodsOperationDTO goodsOperationDTO) {
        if (Objects.requireNonNull(UserContext.getCurrentUser()).getScene().equals(SceneEnums.STORE) || Objects.requireNonNull(UserContext.getCurrentUser()).getScene().equals(SceneEnums.MANAGER) ) {
            goodsIntegrationService.updateGoods(goodsOperationDTO.getGoodsIds(), goodsOperationDTO.getCategoryPathIds());
            return ResultUtil.success();
        } else {
            return ResultUtil.error();
        }
    }

    /**
     * 添加商品分类
     * @param categoryPathSon 分类id
     *
     * @return 是否成功
     */
    @PostMapping("/add/categoryPathSon")
    public ResultMessage<Object> addCategoryPathSon(@RequestParam String ids, @RequestParam String categoryPathSon, @RequestParam String categoryPathSonName) {
        return goodsIntegrationService.addCategoryPathSon(ids, categoryPathSon, categoryPathSonName);
    }

    @ApiOperation(value = "删除商品")
    @DeleteMapping(value = "/delete")
    @ApiImplicitParam(name = "goodsId", value = "商品ID", required = true, paramType = "query", allowMultiple = true)
    public ResultMessage<Object> deleteGoods(@RequestParam List<String> goodsId) {
        String storeId = Objects.requireNonNull(UserContext.getCurrentUser()).getExtendId();
        Boolean result = goodsIntegrationService.deleteGoodsV2(goodsId, storeId);
        return ResultUtil.data(result);
    }


    @ApiOperation(value = "物理删除数据")
    @DeleteMapping(value = "/physicsDelete")
    @ApiImplicitParam(name = "goodsId", value = "商品ID", required = true, paramType = "query", allowMultiple = true)
    public ResultMessage<Object> physicsDelete(@RequestParam List<String> goodsId) {
        String storeId = Objects.requireNonNull(UserContext.getCurrentUser()).getExtendId();
        Boolean result = goodsIntegrationService.deleteGoods(goodsId, storeId);
        return ResultUtil.data(result);
    }

    @ApiOperation(value = "设置商品运费模板")
    @PutMapping(value = "/freight")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "goodsId", value = "商品ID", required = true, paramType = "query", allowMultiple =
                    true),
            @ApiImplicitParam(name = "templateId", value = "运费模板ID", required = true, paramType = "query")
    })
    public ResultMessage<Object> freight(@RequestBody GoodsUpdateFreightDTO goodsUpdateFreightDTO) {
        Boolean result = goodsService.freight(goodsUpdateFreightDTO.getGoodsId(), goodsUpdateFreightDTO.getTemplateId());
        return ResultUtil.data(result);
    }

    @ApiOperation(value = "修改商品库存")
    @PutMapping(value = "/update/stocks")
    public ResultMessage<Object> updateStocks(@RequestBody List<GoodsSkuStockDTO> updateStockList) {
        if (CollUtil.isEmpty(updateStockList)) {
            throw new ServiceException(ResultCode.POINT_GOODS_ACTIVE_STOCK_MUST_ERROR);
        }
        String storeId = Objects.requireNonNull(UserContext.getCurrentUser()).getExtendId();
        // 获取商品skuId集合
        List<String> goodsSkuIds =
                updateStockList.stream().map(GoodsSkuStockDTO::getSkuId).toList();
        // 根据skuId集合查询商品信息
        List<GoodsSku> goodsSkuList = goodsSkuService.list(new LambdaQueryWrapper<GoodsSku>().in(GoodsSku::getId,
                goodsSkuIds).eq(GoodsSku::getStoreId, storeId));

        //设置库存
        for (GoodsSku goodsSku : goodsSkuList) {
            //如果是代理商修改供应商发布的商品库存信息，则抛出异常
            if (Boolean.TRUE.equals(goodsSku.getIsProxyGoods()) && (CharSequenceUtil.isNotEmpty(goodsSku.getSupplierGoodsId()))) {
                throw new ServiceException(ResultCode.PROXY_GOODS_CANT_UPDATE_STOCK);

            }
            for (GoodsSkuStockDTO goodsSkuStockDTO : updateStockList) {
                if (goodsSku.getId().equals(goodsSkuStockDTO.getSkuId())) {
                    goodsSku.setQuantity(goodsSkuStockDTO.getQuantity());
                }
            }
        }

        goodsSkuService.updateStocks(goodsSkuList);
        goodsService.updateStock(goodsSkuList);
        return ResultUtil.success();
    }

    @ApiOperation(value = "通过id获取商品详情")
    @GetMapping(value = "/{id}")
    public ResultMessage<GoodsVO> get(@PathVariable String id) {
        GoodsVO goods = goodsIntegrationService.getGoodsVO(id);
        return ResultUtil.data(goods);
    }

    @ApiOperation(value = "通过id获取商品信息")
    @ApiImplicitParams({@ApiImplicitParam(name = "goodsId", value = "商品ID", required = true, paramType = "path"),
            @ApiImplicitParam(name = "skuId", value = "skuId", required = true, paramType = "path")})
    @GetMapping(value = "/sku/vo/{goodsId}/{skuId}")
    @PageViewPoint(type = PageViewEnum.SKU, id = "#id")
    public ResultMessage<Map<String, Object>> getSku(@NotNull(message = "商品ID不能为空") @PathVariable("goodsId") String goodsId, @NotNull(message =
            "SKU ID不能为空") @PathVariable("skuId") String skuId, String distId) {
        try {
            // 读取选中的列表
            Map<String, Object> map = goodsIntegrationService.getGoodsSkuDetail(goodsId, skuId, distId);
            return ResultUtil.data(map);
        } catch (ServiceException se) {
            log.info(se.getMsg(), se);
            throw se;
        } catch (Exception e) {
            log.error(ResultCode.GOODS_ERROR.message(), e);
            return ResultUtil.error(ResultCode.GOODS_ERROR);
        }
    }

    @ApiOperation(value = "查询盲盒商品")
    @GetMapping("/blindbox")
    public ResultMessage<List<GoodsVO>> geBlindbox() {
        return ResultUtil.data(goodsService.geBlindbox());
    }


//    @ApiOperation(value = "查询第三方平台的商品列表")
//    @GetMapping("/getPlatformGoodsList")
//    public ResultMessage<Object> getPlatformGoodsList(GoodsSearchParams goodsSearchParams) {
//        return goodsService.getPlatformGoodsList(goodsSearchParams);
//    }


    @GetMapping("/setCategoryTree")
    public ResultMessage<Object> setCategoryTree() {
        return goodsService.getCategoryTree();
    }

    @GetMapping("/addGoods")
    public ResultMessage<Object> addGoods(GoodsSearchParams goodsSearchParams) {
        for (int i = 1; i < 26; i++) {
            goodsSearchParams.setPageNumber(i);
            goodsSearchParams.setPageSize(100);
            goodsService.addGoods(goodsSearchParams);
        }
        return ResultUtil.success();
    }

    @GetMapping("/supplyChainGoods")
    public ResultMessage<Object> supplyChainGoods(@RequestParam Integer id) {
        GoodsSearchParams goodsSearchParams = new GoodsSearchParams();
        goodsSearchParams.setCursor(id - 1);
        goodsSearchParams.setPageSize(1);
        goodsService.addGoods(goodsSearchParams);
        return ResultUtil.success();
    }

    @GetMapping("/updateThirdPartyPlatformId")
    public ResultMessage<Object> updateThirdPartyPlatformId() {
        goodsService.updateThirdPartyPlatformId();
        return ResultUtil.success();
    }

    /**
     * 获取下架商品数量
     *
     * @return 数量
     */
    @GetMapping("/getDownCount")
    public ResultMessage<Object> getDownCount(String scene) {
        return goodsService.getDownCount(scene);
    }

    /**
     * 多选比对1688价格
     */
    @SneakyThrows
    @GetMapping("/isDownTow")
    public ResultMessage<Object> isDownTow(@RequestParam("goodsId") String goodsId) {
        if (StringUtils.isEmpty(goodsId)) {
            return ResultUtil.error(500,"商品列表为空");
        }
//        String goodsIds = goodsId.stream().collect(Collectors.joining(","));
        goodsService.isDown(goodsId);
        return ResultUtil.success();
    }

    @GetMapping("/clearCacheByStoreId")
    public ResultMessage<Object> clearCacheByStoreId(@RequestParam String storeId) {
        return goodsService.clearCacheByStoreId(storeId);
    }


    /**
     * 同步壹邦玖商品，用于供应链新增商品时定时去同步
     */
    @Scheduled(cron = "0 0 */1 * * ?")
    @GetMapping("/syncGoods")
    public void syncGoods() {
        RLock lock = null;
        try {
            lock = redisson.getLock(LockPrefix.WALLET.getPrefix());
            lock.lock(100, TimeUnit.SECONDS);
            goodsService.syncGoods();
        } catch (Exception e) {
            log.error("error == {}", e.getMessage());
            e.printStackTrace();
        } finally {
            if (lock != null) {
                lock.unlock();
                log.info("强制释放锁");
            }
        }
    }

    /**
     * 添加盲盒商品
     *
     * @return 是否成功
     */
    @PostMapping("/mh/add")
    public ResultMessage<Object> add(@Valid @RequestBody GoodsVO goodsVO) {
        return goodsService.add(goodsVO);
    }

    /**
     * 删除盲盒商品
     *
     * @param ids id
     * @return 是否成功
     */
    @DeleteMapping("/mh/delete")
    public ResultMessage<Object> mhDelete(@RequestParam String ids) {
        return goodsService.mhDelete(ids);
    }

    /**
     * 修改盲盒商品
     *
     * @param goodsVO 商品
     * @return 是否成功
     */
    @PutMapping("/mh/update")
    public ResultMessage<Object> mhUpdate(@RequestBody GoodsVO goodsVO) {
        return goodsService.mhUpdate(goodsVO);
    }

    /**
     * 商品发布状态变更， 1发布，2撤销发布
     * @return
     */
    @PutMapping("/mh/publish/{publishType}")
    public ResultMessage<Object> mhPublish(@PathVariable Integer publishType, @RequestParam String id) {
        return goodsService.mhPublish(publishType, id);
    }


    @ApiOperation(value = "查询门票商品下sku列表")
    @GetMapping("/getGoodsSkuList")
    public ResultMessage<List<GoodsSku>> getGoodsSkuList () {
        Goods goods = goodsService.getTicketGoods();
        if (null != goods) {
            return ResultUtil.data(goodsSkuService.getGoodsSkuListByGoodsId(goods.getId()));
        }
        return ResultUtil.data(new ArrayList<>());
    }

    @ApiOperation(value = "根据门票规格名称获取门票规格")
    @RequestMapping("/getGoodsSkuByName")
    public ResultMessage<GoodsSku> getGoodsSkuByName (@RequestParam String skuName) {
        Goods goods = goodsService.getTicketGoods();
        if (null != goods) {
            return ResultUtil.data(goodsSkuService.getBySkuName(goods.getId(), skuName));
        }
        return ResultUtil.data(new GoodsSku());
    }

    /**
     * 首页商品数量统计
     */
    @GetMapping("/commodity/quantity/statistics")
    public ResultMessage<HomeResult> commodityQuantityStatistics() {
        return goodsService.commodityQuantityStatistics();
    }


    @GetMapping("/getSupplierByPage")
    @ApiOperation("运营中心-服务商-供货商家列表")
    public ResultMessage<Page<OperationCenterSupplierVo>> getSupplierByPage(OperationCenterSupplierDTO dto) {
        return ResultUtil.data(goodsService.getSupplierByPage(dto));
    }

    @GetMapping("/getSupplierByGoodsDownRecordPage")
    @ApiOperation("运营中心-服务商-供货商家列表-商品下架详情页面")
    public ResultMessage<Page<GoodsDownRecord>> getSupplierByGoodsDownRecordPage(GoodsDownRecordDTO dto) {
        return ResultUtil.data(goodsDownRecordService.getSupplierByGoodsDownRecordPage(dto));
    }

    @GetMapping("/selectStoreShareList")
    @ApiOperation("PLUS会员礼包-获取店主分享列表商品")
    public ResultMessage<Page<StoreShareDTO>> selectStoreShareList(StoreShareDTO dto) {
        return ResultUtil.data(goodsSkuService.selectStoreShareList(dto));
    }

    /**
     * 年货节
     */
    @GetMapping("/getNewYearShoppingFestival")
    public ResultMessage<Map<String, Object>> getNewYearShoppingFestival() {
        Map<String, Object> map = new ConcurrentHashMap<>();
        map.put("status", 1);
        map.put("img", "http://xiazai.chainlettre06.com/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20250120210004.jpg");
        return ResultUtil.data(map);
    }

}
